/**
 * Copyright (C) 2012 The SkyTvOS Project
 * <p/>
 * Version     Date           Author
 * ─────────────────────────────────────
 * 2015年4月7日         Root.Lu
 */

package com.coocaa.x.service.litecontent;

import android.content.Context;
import android.net.Uri;
import android.os.IBinder;
import android.os.RemoteException;

import com.coocaa.x.framework.app.CoocaaService.AIDLInterface;
import com.coocaa.x.service.litecontent.LiteContentProvider.ResourceHandler;
import com.coocaa.x.service.litecontent.aidl.ILiteContentService;
import com.coocaa.x.service.litecontent.aidl.ILiteContentServiceReceiver;
import com.coocaa.x.service.litecontent.providers.apps.AppsProvider;
import com.coocaa.x.service.litecontent.providers.setting.SettingProvider;
import com.coocaa.x.service.litecontent.providers.skyview.SkyViewProvider;
import com.coocaa.x.service.litecontent.providers.store.StoreProvider;
import com.coocaa.x.service.litecontent.providers.system.SystemProvider;
import com.coocaa.x.uipackage.SkinManager;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class LiteContentServiceStub extends ILiteContentService.Stub implements
        ILiteContentServiceNotify {
    private static final Map<String, LiteContentProvider> providers = new HashMap<String, LiteContentProvider>();
    private List<AIDLInterface<ILiteContentServiceReceiver>> receivers = new ArrayList<AIDLInterface<ILiteContentServiceReceiver>>();
    private ThreadPoolExecutor executor = null;

    public LiteContentServiceStub(Context context) {
        SkinManager.getInstance().init(context, "");
        executor = new ThreadPoolExecutor(1, 5, 10, TimeUnit.DAYS,
                new LinkedBlockingQueue<Runnable>(), new ThreadFactory() {
            @Override
            public Thread newThread(Runnable r) {
                Thread thread = new Thread(r, "LiteContentServiceNotifyThread");
                return thread;
            }
        });
        executor.prestartAllCoreThreads();

        ResourceHandler.mContext = context;
        LiteContentProvider.setLiteContentServiceNotify(this);
        addProvider(new SettingProvider(context));
        addProvider(new SkyViewProvider(context));
        addProvider(new AppsProvider(context));
        addProvider(new SystemProvider(context));
        addProvider(new StoreProvider(context));
    }

    private void addProvider(LiteContentProvider provider) {
        synchronized (providers) {
            providers.put(provider.myScheme(), provider);
        }
    }

    @Override
    public String call(String uri) throws RemoteException {
        Uri mUri = Uri.parse(uri);
        String scheme = mUri.getScheme();

        LiteContentProvider provider = null;
        synchronized (providers) {
            provider = providers.get(scheme);
        }
        if (provider != null)
            try {
                return provider.call(mUri).toString();
            } catch (Exception e) {
                e.printStackTrace();
                throw new RemoteException(e.getMessage());
            }
        throw new RemoteException("Has no provider to handle " + scheme);
    }

    @Override
    public void registerReceiver(ILiteContentServiceReceiver receiver) throws RemoteException {
        synchronized (receivers) {
            if (receiver != null) {
                IBinder binder = receiver.asBinder();
                for (AIDLInterface<ILiteContentServiceReceiver> _i : receivers) {
                    if (_i.binder == binder)
                        return;
                }
                AIDLInterface<ILiteContentServiceReceiver> i = new AIDLInterface<ILiteContentServiceReceiver>(
                        binder, receiver);
                receivers.add(i);
            }
        }
    }

    @Override
    public void removeReceiver(ILiteContentServiceReceiver receiver) throws RemoteException {
        synchronized (receivers) {
            if (receiver != null) {
                IBinder binder = receiver.asBinder();
                for (AIDLInterface<ILiteContentServiceReceiver> i : receivers) {
                    if (i.binder == binder) {
                        receivers.remove(i);
                        break;
                    }
                }
            }
        }
    }

    @Override
    public void sendNotify(final String uri, final String data) {
        synchronized (receivers) {
            for (final AIDLInterface<ILiteContentServiceReceiver> i : receivers) {
                executor.execute(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            i.i.onReceive(uri, data);
                        } catch (Exception e) {
                            e.printStackTrace();
                        }

                    }
                });
            }
        }
    }
}
